home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / pyshared / CommandNotFound / CommandNotFound.py < prev    next >
Text File  |  2008-10-15  |  7KB  |  150 lines

  1. # (c) Zygmunt Krynicki 2005, 2006, 2007, 2008
  2. # Licensed under GPL, see COPYING for the whole text
  3.  
  4. import sys, os, os.path, gdbm, posix, grp
  5. from util import gettext_wrapper as _
  6.  
  7. class BinaryDatabase:
  8.     def __init__(self, filename):
  9.         self.db = None
  10.         if filename.endswith(".db"):
  11.             try:
  12.                 self.db = gdbm.open(filename, "r")
  13.             except gdbm.error, err:
  14.                 print >>sys.stderr, "Unable to open binary database %s: %s" % (filename, err)
  15.     def lookup(self, key):
  16.         if self.db and self.db.has_key(key):
  17.             return self.db[key]
  18.         else:
  19.             return None
  20.  
  21. class FlatDatabase:
  22.     def __init__(self, filename):
  23.         self.rows = []
  24.         dbfile = file(filename)
  25.         for line in (line.strip() for line in dbfile):
  26.             self.rows.append(line.split("|"))
  27.         dbfile.close()
  28.     def lookup(self, column, text):
  29.         result = []
  30.         for row in self.rows:
  31.             if row[column] == text:
  32.                 result.append(row)
  33.         return result
  34.     def createColumnByCallback(self, cb, column):
  35.         for row in self.rows:
  36.             row.append(cb(row[column]))
  37.     def lookupWithCallback(self, column, cb, text):
  38.         result = []
  39.         for row in self.rows:
  40.             if cb(row[column],text):
  41.                 result.append(row)
  42.         return result
  43.  
  44. class ProgramDatabase:
  45.     (PACKAGE, BASENAME_PATH) = range(2)
  46.     def __init__(self, filename):
  47.         basename = os.path.basename(filename)
  48.         (self.arch, self.component) = basename.split(".")[0].split("-")
  49.         self.db = BinaryDatabase(filename)
  50.     def lookup(self, command):
  51.         result = self.db.lookup(command)
  52.         if result:
  53.             return result.split("|")
  54.         else:
  55.             return []
  56.  
  57. class CommandNotFound:
  58.     programs_dir = "programs.d"
  59.     prefixes = ("/bin", "/usr/bin", "/usr/local/bin", "/sbin", "/usr/sbin", "/usr/local/sbin", "/usr/games")
  60.     def __init__(self, data_dir=os.sep.join(('/','usr','share','command-not-found'))):
  61.         self.programs = []
  62.         self.sources_list = self._getSourcesList()
  63.         for filename in os.listdir(os.path.sep.join([data_dir, self.programs_dir])):
  64.             self.programs.append(ProgramDatabase(os.path.sep.join([data_dir, self.programs_dir, filename])))
  65.         try:
  66.             self.user_can_sudo = grp.getgrnam("admin")[2] in posix.getgroups()
  67.         except KeyError:
  68.             self.user_can_sudo = False
  69.     def getPackages(self, command):
  70.         result = set()
  71.         for db in self.programs:
  72.             result.update([(pkg,db.component) for pkg in db.lookup(command)])
  73.         return list(result)
  74.     def getBlacklist(self):
  75.         try:
  76.             blacklist = file(os.sep.join((os.getenv("HOME", "/root"), ".command-not-found.blacklist")))
  77.             return [line.strip() for line in blacklist if line.strip() != ""]
  78.         except IOError:
  79.             return []
  80.         else:
  81.             blacklist.close()
  82.     def _getSourcesList(self):
  83.         try:
  84.             import apt_pkg
  85.             from aptsources.sourceslist import SourcesList
  86.             apt_pkg.init()
  87.         except (SystemError, ImportError), e:
  88.             return []
  89.         sources_list = set([])
  90.         for source in SourcesList():
  91.              if not source.disabled and not source.invalid:
  92.                  for component in source.comps:
  93.                      sources_list.add(component)
  94.         return sources_list
  95.     def advise(self, command, ignore_installed=False):
  96.         def _in_prefix(prefix, command):
  97.             " helper that returns if a command is found in the given prefix "
  98.             return (os.path.exists(os.path.join(prefix, command)) and 
  99.                     not os.path.isdir(os.path.join(prefix, command)))
  100.  
  101.         if command.startswith("/"):
  102.             if os.path.exists(command):
  103.                 prefixes = [os.path.dirname(command)]
  104.             else:
  105.                 prefixes = []
  106.         else:
  107.             prefixes = [prefix for prefix in self.prefixes if _in_prefix(prefix, command)]
  108.         if prefixes and not ignore_installed:
  109.             if len(prefixes) == 1:
  110.                 print >>sys.stderr, _("Command '%(command)s' is available in '%(place)s'") % {"command": command, "place": os.path.join(prefixes[0], command)}
  111.             else:
  112.                 print >>sys.stderr, _("Command '%(command)s' is available in the following places") % {"command": command}
  113.                 for prefix in prefixes:
  114.                     print >>sys.stderr, " * %s" % os.path.join(prefix, command)
  115.             missing = list(set(prefixes) - set(os.getenv("PATH", "").split(":")))
  116.             if len(missing) > 0:
  117.                 print >>sys.stderr, _("The command could not be located because '%s' is not included in the PATH environment variable.") % ":".join(missing)
  118.                 if "sbin" in ":".join(missing):
  119.                     print >>sys.stderr, _("This is most likely caused by the lack of administrative priviledges associated with your user account.")
  120.             return False
  121.         if command in self.getBlacklist():
  122.             return False
  123.         packages = self.getPackages(command)
  124.         if len(packages) == 1:
  125.             print >>sys.stderr, _("The program '%s' is currently not installed. ") % command,
  126.             if posix.geteuid() == 0:
  127.                 print >>sys.stderr, _("You can install it by typing:")
  128.                 print >>sys.stderr, "apt-get install %s" %  packages[0][0]
  129.             elif self.user_can_sudo:
  130.                 print >>sys.stderr, _("You can install it by typing:")
  131.                 print >>sys.stderr, "sudo apt-get install %s" %  packages[0][0]
  132.             else:
  133.                 print >>sys.stderr, _("To run '%(command)s' please ask your administrator to install the package '%(package)s'") % {'command': command, 'package': packages[0][0]}
  134.             if not packages[0][1] in self.sources_list:
  135.                 print >>sys.stderr, _("You will have to enable the component called '%s'") % packages[0][1]
  136.         elif len(packages) > 1:
  137.             print >>sys.stderr, _("The program '%s' can be found in the following packages:") % command
  138.             for package in packages:
  139.                 if package[1] in self.sources_list:
  140.                     print >>sys.stderr, " * %s" % package[0]
  141.                 else:
  142.                     print >>sys.stderr, " * %s" % package[0] + " (" + _("You will have to enable component called '%s'") % package[1] + ")"
  143.             if posix.geteuid() == 0:
  144.                 print >>sys.stderr, _("Try: %s <selected package>") % "apt-get install"
  145.             elif self.user_can_sudo:
  146.                 print >>sys.stderr, _("Try: %s <selected package>") % "sudo apt-get install"
  147.             else:
  148.                 print >>sys.stderr, _("Ask your administrator to install one of them")
  149.         return len(packages) > 0
  150.